﻿using System;
using System.Xml;
using System.Xml.XPath;
using System.Xml.Xsl;
using InfoJetSoft.Service.Entity;

namespace InfoJetSoft.Service.Util
{

    public class ExtXdDateFunction : IExtensionFunctions
	{
		public static string[] DateTimeFormats = { "yyyy-MM-dd'T'HH:mm:ss", "yyyy-MM-dd" };

		private Form form = null;

		public ExtXdDateFunction( Form frm ){
			this.form = frm;
        }

        //CID 0755 //2011.01.14 //Begin
        #region IExtensionFunction Members

        public string Prefix
        {
            get { return this.form.Manifest.NsResolver.GetPrefix(this.NamespaceURI); }
        }

        public string NamespaceURI
        {
            get { return JetConstant.URI_XDDATE; }
        }

        public IXsltContextFunction ResolveFunction(string prefix, string name, XPathResultType[] argTypes)
        {
            if (name.Equals("Today"))
            {
                return new XPathFunction(this.form, prefix, name, 0, 0, argTypes, XPathResultType.String);
            }
            else if (name.Equals("Now"))
            {
                return new XPathFunction(this.form, prefix, name, 0, 0, argTypes, XPathResultType.String);
            }
            //CID 0755 //2011.05.04 //Begin
            else if (name.Equals("AddDays"))
            {
                return new XPathFunction(this.form, prefix, name, 2, 2, argTypes, XPathResultType.String);
            }
            else if (name.Equals("AddSeconds"))
            {
                return new XPathFunction(this.form, prefix, name, 2, 2, argTypes, XPathResultType.String);
            }
            //CID 0755 //2011.05.04 //End
            else
            {
                throw new InfoJetException("Unimplemented Function.", prefix + ":" + name);
            }
        }

        public object InvokeFunction(string prefix, string name, XsltContext xsltContext, object[] args, XPathNavigator docContext)
        {
            if (name.Equals("Today"))
            {
                return this.Today();
            }
            else if (name.Equals("Now"))
            {
                return this.Now();
            }
            //CID 0755 //2011.05.04 //Begin
            else if (name.Equals("AddDays"))
            {
                return this.AddDays(args[0], args[1]);
            }
            else if (name.Equals("AddSeconds"))
            {
                return this.AddSeconds(args[0], args[1]);
            }
            //CID 0755 //2011.05.04 //End
            else
            {
                throw new InfoJetException("Unimplemented Function.", prefix + ":" + name);
            }
        }

        #endregion
        //CID 0755 //2011.01.14 //End

		public string Today() 
		{
			return DateTime.Now.ToString( "yyyy-MM-dd" );
		}
		
		public string Now()
		{
			return DateTime.Now.ToString( "yyyy-MM-dd'T'HH:mm:ss" );
		}

		public string AddDays( object param1, object param2 )
		{
			string dateValue = parseDateValue( param1 );
			if( dateValue.Trim().Length <= 0 )
			{
				return "";
			}

			try
			{
				DateTime date = DateTime.ParseExact( dateValue, DateTimeFormats, 
						System.Threading.Thread.CurrentThread.CurrentCulture.DateTimeFormat, 
						System.Globalization.DateTimeStyles.None );
				double[] addValue = parseAddValue( param2 );
				if( addValue == null )
				{
					return "";
				}

				date = date.AddDays( addValue[ 0 ] );
				return date.ToString( "yyyy-MM-dd" );
			}
			catch( Exception e )
			{
				return "ERR?";
			}
		}

		public string AddSeconds( object param1, object param2 )
		{
			string dateValue = parseDateValue( param1 );
			if( dateValue.Trim().Length <= 0 )
			{
				return "";
			}

			try
			{
				DateTime date = DateTime.ParseExact( dateValue, DateTimeFormats, 
					System.Threading.Thread.CurrentThread.CurrentCulture.DateTimeFormat, 
					System.Globalization.DateTimeStyles.None );
				double[] addValue = parseAddValue( param2 );
				if( addValue == null )
				{
					return "";
				}

				date = date.AddSeconds( addValue[ 0 ] );
				return date.ToString( "yyyy-MM-dd'T'HH:mm:ss" );
			}
			catch( Exception e )
			{
				return "ERR?";
			}
		}

		private string parseDateValue( object param1 )
		{
			string dateValue = null;
			if (param1 is XPathNodeIterator)
			{
				XPathNodeIterator nodeIterator1 = (XPathNodeIterator) param1;
				if (nodeIterator1.MoveNext())
				{
					dateValue = nodeIterator1.Current.Value;
				}
			}
			else if ( param1 is string )
			{
				dateValue = (string)param1;
			}
			if( dateValue == null || dateValue.Trim().Length <= 0 )
			{
				dateValue = "";
			}
			return dateValue;
		}

		private double[] parseAddValue( object param2 )
		{
			double addValue = 0;
			if( param2 is double )
			{
				addValue = (double)param2;
			}
			else if( param2 is XPathNodeIterator )
			{
				XPathNodeIterator nodeIterator2 = (XPathNodeIterator) param2;
				if (nodeIterator2.MoveNext())
				{
					if( nodeIterator2.Current.Value.Trim().Length <= 0 )
					{
						return null;
					}
					addValue = ConvertUtil.parseDoubleWithLocalDecimalSeparator( nodeIterator2.Current.Value );
				}
				else
				{
					return null;
				}
			}
			else
			{
				addValue = ConvertUtil.parseDoubleWithLocalDecimalSeparator( param2.ToString() );
			}
			return new double[]{ addValue };
		}
    }
}